﻿using DotNetCore.CAP;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using MT.Enterprise.Utils.Extensions;
using Newtonsoft.Json;
using Nito.AsyncEx.Synchronous;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.EmailHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Business.AccountOpenChange;
using NP.BPMReportPlatform.Entities.BPM_Business.YCLWLJGZSYC;
using NP.BPMReportPlatform.Entities.BPM_Engine;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.Entities.BPM_Process;
using NP.BPMReportPlatform.RecurringJobs.Dto;
using NP.BPMReportPlatform.RecurringJobs.Dto.AccountOpenChage;
using NP.BPMReportPlatform.RecurringJobs.Dto.YCLWLJGZSYC;
using NP.BPMReportPlatform.Utilities;
using NP.BPMReportPlatform.YCLWLJGZSYC.Dto;
using NP.Enterprise.Utils.Http;
using Serilog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NP.BPMReportPlatform.RecurringJobs
{
    /// <summary>
    /// 每月4号发送邮件提醒未提交和未审批流程
    /// </summary>
    public class AccountOpenChangeRecurringJob : BpmReportPlatformRecurringJob, IAccountOpenChangeRecurringJob
    {
        private readonly SqlSugarClient _db, _dbPlatform, _dbEngine, _dbProcess;
        private readonly INPRestHttpHelper _nPRestHttp;
        private readonly IConfiguration _configuration;
        private readonly ILogger _logger;
        private readonly IEmailAPPService _emailAPPService;
        private readonly ICapPublisher _capBus;
        private IHostingEnvironment _env;
        private readonly string TestEmail = "yangxin@movit-tech.com";
        private readonly string TestCCEmail = "yangxin@movit-tech.com";

        public AccountOpenChangeRecurringJob(
            ISqlSugarAppService sqlSugarAppService, 
            IConfiguration configuration,
            INPRestHttpHelper nPRestHttp,
            ILogger logger,
            IEmailAPPService emailAPPService,
            ICapPublisher capBus,
            IHostingEnvironment env)
        {
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _dbEngine = sqlSugarAppService.GetEngineInstance();
            _dbProcess = sqlSugarAppService.GetProcessInstance();
            _nPRestHttp = nPRestHttp;
            _configuration = configuration;
            _logger = logger;
            _emailAPPService = emailAPPService;
            _capBus = capBus;
            _env = env;
        }

        /// <summary>
        /// 给管理员发送未完善账号邮件提醒
        /// </summary>
        /// <returns></returns>
        public async Task SendNoticeEmailForIncompleteAccount(string title)
        {
            try
            {
                var PCStartUrl = await GetPCStartUrl();
                if (string.IsNullOrEmpty(PCStartUrl))
                {
                    _logger.Error("SendNoticeEmailForIncompleteAccount，流程未找到");
                    return;
                }

                var list = await GetHistoryAccountList();
                var adminWorkNumbers = list.Select(x => x.AdminWorkNumber).Distinct().ToList();
                var adminEmails = await _dbPlatform.Queryable<Users>()
                    .Where(x => x.Status == 1 && adminWorkNumbers.Contains(x.WorkNumber))
                    .Select(x => new { x.Email, x.WorkNumber }).ToListAsync();
                var groupList = list.GroupBy(x => x.AdminWorkNumber).ToList();
                foreach (var groupItem in groupList)
                {
                    var item = groupItem.First();
                    var email = adminEmails.FirstOrDefault(x => x.WorkNumber == item.AdminWorkNumber)?.Email;
                    if (string.IsNullOrEmpty(email))
                    {
                        continue;
                    }

                    email = GetToEmails(email);

                    var sendNoticeList = groupItem.ToList();
                    sendNoticeList.ForEach(q =>
                    {
                        q.Url = $"{PCStartUrl}&instanceNumber={q.InstanceNumber}";
                    });
                    await SendNoticeEmail(groupItem.ToList(), email, title);
                }
            }
            catch(Exception ex)
            {
                _logger.Error($"SendNoticeEmailForIncompleteAccount，{ex.Message}");
            }
        }

        public async Task SendNoticeEmailToAdminForIncompleteAccount(string adminEmails, string title)
        {
            if (string.IsNullOrEmpty(adminEmails))
            {
                return;
            }

            var emails = adminEmails.Split(",", StringSplitOptions.RemoveEmptyEntries).ToList();
            if (!emails.Any())
            {
                return;
            }

            try
            {
                var PCStartUrl = await GetPCStartUrl();
                if (string.IsNullOrEmpty(PCStartUrl))
                {
                    _logger.Error("SendNoticeEmailForIncompleteAccount，流程未找到");
                    return;
                }

                var sendNoticeList = await GetHistoryAccountList();
                sendNoticeList = sendNoticeList.OrderBy(x => x.InstanceNumber).ToList();
                sendNoticeList.ForEach(q =>
                {
                    q.Url = $"{PCStartUrl}&instanceNumber={q.InstanceNumber}";
                });
                foreach (var email in emails)
                {   
                    await SendNoticeEmail(sendNoticeList, email, title);
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"SendNoticeEmailToAdminForIncompleteAccount，{ex.Message}");
            }
        }

        /// <summary>
        /// 发送未完善账号提醒邮件
        /// </summary>
        /// <param name="esbData"></param>
        /// <param name="email"></param>
        /// <param name="ccEmails"></param>
        /// <returns></returns>
        private async Task SendNoticeEmail(List<HistoryAccountDto> esbData, string email, string title, string ccEmails = "")
        {
            var topic = "您好，您管理的公共平台账号/店铺，有信息没有完善，请尽快处理！";
            var replaceContent = "";
            var content = "";
            var templateName = "AccountOpenChangeNotice.cshtml";

            title = string.IsNullOrWhiteSpace(title) ? "您好，您管理的公共平台账号/店铺，有信息待完善，请点击以下链接去提交完整信息，谢谢！" : title;

            esbData.ForEach(x =>
            {
                replaceContent += @$"<tr>
                                    <th>{x.PlatformName}</th>   
                                    <th>{x.ApplyAccount}</th>
                                    <th><a href='{x.Url}' target=""_blank"">{x.Url}</a></th>                     
                                    </tr>";
            });
            if (!string.IsNullOrEmpty(templateName))
            {
                content = _emailAPPService.GenerateEmailTemplate(templateName);
                content = content.Replace("{title}", title);
                content = !string.IsNullOrEmpty(replaceContent) ?
                    content.Replace("{content}", replaceContent) : string.Empty;
            }
            if (!string.IsNullOrEmpty(content) && !string.IsNullOrEmpty(email))
            {
                await _capBus.PublishAsync("bpmnew.EmailAppService.SendEmailAsync",
                  new SendEmailSimpleDto()
                  {
                      To = GetToEmails(email),
                      Subject = topic,
                      Body = content,
                      CC = ccEmails
                  });
            }
        }

        /// <summary>
        /// 历史流程模糊查询
        /// </summary>
        /// <param name="parms"></param>
        /// <returns></returns>
        public async Task<List<HistoryAccountDto>> GetHistoryAccountList()
        {
            var list = await _db.Queryable<AccountOpenChangeResult>()
                .Where(x => x.IsClosed == 0 && x.IsCanSendNoticeEmail != null && x.IsCanSendNoticeEmail.Value && 
                x.InstanceNumber.StartsWith("P"))
                .Select(x => new HistoryAccountDto
                {
                    InstanceNumber = x.InstanceNumber,
                    ApplyAccount = x.ApplyAccount,
                    PrincipalName = x.PrincipalName,
                    AddUserName = x.AddUserName,
                    AddTime = x.AddTime.ToString("yyyy-MM-dd HH:mm:ss"),
                    AddDatetime = x.AddTime,
                    OriginInstanceNumber = x.OriginInstanceNumber,
                    Sn = x.Sn,
                    PlatformName = x.PlatformName,
                    SubPlatformName = x.SubPlatformName,
                    AdminWorkNumber = x.AdminWorkNumber,
                }).OrderBy(x => x.ApprovedTime, OrderByType.Desc).ToListAsync();
            var headers = await _db.Queryable<AccountOpenChangeHeader, BusinessProcessesNew>(
                (x, b) => x.InstanceNumber == b.InstanceId)
                .Where(x => list.Select(q => q.OriginInstanceNumber).Contains(x.OriginInstanceNumber))
                .Select((x, b) => new
                {
                    x.ApprovedTime,
                    x.OriginInstanceNumber,
                    x.InstanceNumber,
                    x.OperationType,
                    b.ProcessStatusCode
                }).ToListAsync();
            var instanceNumbers = headers.Where(x => x.ProcessStatusCode == "processing").Select(x => x.InstanceNumber).ToList();
            var instanceStates = instanceNumbers.Any() ?
                await _dbEngine.Queryable<Instances, InstanceStates>(
                (x, b) => x.InstanceId.Equals(b.InstanceId))
                .Where((x, b) => instanceNumbers.Contains(x.Number) && b.Status == 1)
                .Select(x => x.Number).ToListAsync() : new List<string>();
            list.ForEach(x =>
            {
                x.ReferProcessID = headers.Where(q => q.OriginInstanceNumber == x.OriginInstanceNumber &&
                    q.ApprovedTime != null).OrderByDescending(q => q.ApprovedTime).FirstOrDefault()?.InstanceNumber ?? "";
                x.OperationType = headers.FirstOrDefault(q => q.OriginInstanceNumber == x.OriginInstanceNumber &&
                    q.ProcessStatusCode == "processing" && instanceStates.Contains(q.InstanceNumber))?.OperationType;
                x.IsChanging = headers.FirstOrDefault(q => q.OriginInstanceNumber == x.OriginInstanceNumber &&
                    q.ProcessStatusCode == "processing" && instanceStates.Contains(q.InstanceNumber)) != null;
            });
            return list.Where(x => !x.IsChanging).ToList();
        }

        private async Task<bool> GetIsAdmin(string workNumber)
        {
            var managerStr = (await _db.Queryable<KeyValues>()
                .Where(x => x.CatalogCode == "AccountOpenChangeManager").FirstAsync())?.Name ?? "";
            return !string.IsNullOrWhiteSpace(workNumber) &&
                managerStr.Split(",", StringSplitOptions.RemoveEmptyEntries).Contains(workNumber);
        }

        private string GetToEmails(string emails)
        {
            return _env.IsProduction() ? emails : TestEmail;
        }

        private string GetToCCEmails(string emails)
        {
            return _env.IsProduction() ? emails : TestCCEmail;
        }

        /// <summary>
        /// 获取流程发起页面url
        /// </summary>
        /// <returns></returns>
        private async Task<string> GetPCStartUrl()
        {
            var process = await _dbProcess.Queryable<Processes>().FirstAsync(x => x.BTID.Equals("AccountOpenChange") && x.InUse == 1);
            if (process == null)
            {
                return "";
            }

            return string.Format(_configuration["BPM:PCStartUrl"], process.ProcessId);
        }
    }
}
